package com.jsrana.idea.plugin.ideaweather.ui;

import com.intellij.ide.util.PropertiesComponent;
import com.jsrana.idea.plugin.ideaweather.IdeaWeatherPlugin;
import com.jsrana.idea.plugin.ideaweather.util.HttpUtil;
import com.jsrana.idea.plugin.ideaweather.worker.WeatherWorker;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.swing.*;
import javax.swing.border.Border;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class OptionsDialog
        extends JDialog {
    private JPanel contentPane;
    private JButton buttonOK;
    private JTextField location;
    private JRadioButton fehrenheightRadioButton;
    private JRadioButton celciusRadioButton;
    private JDialog locationSelectionDialog;
    private String locationText = "";
    private DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    private int currentLabelIndex = 0;
    Border paddingBorder = BorderFactory.createEmptyBorder( 5, 5, 5, 5 );
    Map<String, String> locationMap = new HashMap<String, String>();

    public OptionsDialog() {
        setContentPane( contentPane );
        setModal( true );
        getRootPane().setDefaultButton( buttonOK );

        buttonOK.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                onOK();
            }
        } );

        // call onCancel() when cross is clicked
        setDefaultCloseOperation( DO_NOTHING_ON_CLOSE );
        addWindowListener( new WindowAdapter() {
            public void windowClosing( WindowEvent e ) {
                onCancel();
            }
        } );

        // call onCancel() on ESCAPE
        contentPane.registerKeyboardAction( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                onCancel();
            }
        }, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );

        fehrenheightRadioButton.addMouseListener( new MouseAdapter() {
            @Override public void mouseReleased( MouseEvent e ) {
                super.mouseReleased( e );
                if ( fehrenheightRadioButton.isSelected() ) {
                    PropertiesComponent.getInstance().setValue( IdeaWeatherPlugin.PROPERTY_UNIT, "f" );
                }
            }
        } );

        celciusRadioButton.addMouseListener( new MouseAdapter() {
            @Override public void mouseReleased( MouseEvent e ) {
                super.mouseReleased( e );
                if ( celciusRadioButton.isSelected() ) {
                    PropertiesComponent.getInstance().setValue( IdeaWeatherPlugin.PROPERTY_UNIT, "c" );
                }
            }
        } );

        location.addKeyListener( new KeyAdapter() {
            @Override public void keyReleased( KeyEvent e ) {
                super.keyReleased( e );

                int keycode = e.getKeyCode();
                if ( keycode == KeyEvent.VK_ESCAPE ) {

                }
                else {
                    locationText = location.getText();
                    AutoComplete autoComplete = new AutoComplete();
                    autoComplete.execute();
                }
            }
        } );

        if ( "f".equals( PropertiesComponent.getInstance().getValue( IdeaWeatherPlugin.PROPERTY_UNIT, IdeaWeatherPlugin.DEFAULT_UNIT ) ) ) {
            fehrenheightRadioButton.setSelected( true );
        }
        else {
            celciusRadioButton.setSelected( true );
        }

        location.setText( PropertiesComponent.getInstance().getValue( IdeaWeatherPlugin.PROPERTY_LOCATION, IdeaWeatherPlugin.DEFAULT_LOCATION ) );
    }

    private void onOK() {
        new WeatherWorker().execute();

        // add your code here
        dispose();
    }

    private void onCancel() {
        // add your code here if necessary
        dispose();
    }

    class AutoComplete
            extends SwingWorker {
        String xml = "";

        @Override
        protected Object doInBackground()
                throws Exception {
            if ( locationText != null && locationText.length() > 4 ) {
                xml = HttpUtil.getText( "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D%22" + locationText + "%22&format=xml" );
            }
            else {
                xml = "";
            }
            return null;
        }

        @Override
        protected void done() {
            if ( xml.length() > 0 ) {
                try {
                    DocumentBuilder db = dbf.newDocumentBuilder();
                    Document doc = db.parse( new InputSource( new ByteArrayInputStream( xml.getBytes( "utf-8" ) ) ) );
                    Element docElement = doc.getDocumentElement();

                    NodeList nl = docElement.getElementsByTagName( "place" );
                    if ( nl != null && nl.getLength() > 0 ) {
                        locationMap.clear();
                        currentLabelIndex = 0;
                        if ( locationSelectionDialog == null ) {
                            locationSelectionDialog = new JDialog();
                            locationSelectionDialog.setUndecorated( true );
                            locationSelectionDialog.getContentPane().setLayout( new GridLayout( 0, 1 ) );
                            locationSelectionDialog.setModal( true );
                        }
                        locationSelectionDialog.getContentPane().removeAll();
                        final JTextField textField = new JTextField();
                        textField.setText( locationText );
                        textField.addKeyListener( new KeyAdapter() {
                            @Override public void keyReleased( KeyEvent e ) {
                                if ( e.getKeyCode() == KeyEvent.VK_ESCAPE ) {
                                    locationText = "";
                                    location.setText( "" );
                                    locationSelectionDialog.dispose();
                                }
                                else if ( e.getKeyCode() == KeyEvent.VK_DOWN ) {
                                    int componenCount = textField.getParent().getComponentCount();
                                    if ( ++currentLabelIndex < componenCount ) {
                                        if ( currentLabelIndex > 1 ) {
                                            textField.getParent().getComponent( currentLabelIndex - 1 ).setBackground( Color.WHITE );
                                        }
                                        JLabel label = ( JLabel ) textField.getParent().getComponent( currentLabelIndex );
                                        label.setBackground( Color.GREEN );
                                        textField.setText( label.getText() );
                                    }
                                    else {
                                        --currentLabelIndex;
                                    }
                                }
                                else if ( e.getKeyCode() == KeyEvent.VK_UP ) {
                                    if ( currentLabelIndex > 1 ) {
                                        textField.getParent().getComponent( currentLabelIndex ).setBackground( Color.WHITE );
                                        JLabel label = ( JLabel ) textField.getParent().getComponent( --currentLabelIndex );
                                        label.setBackground( Color.GREEN );
                                        textField.setText( label.getText() );
                                    }
                                }
                                else if ( e.getKeyCode() == KeyEvent.VK_ENTER ) {
                                    locationText = textField.getText();
                                    if ( locationText != null && locationText.length() > 0 ) {
                                        location.setText( locationText );
                                        PropertiesComponent.getInstance().setValue( IdeaWeatherPlugin.PROPERTY_LOCATION, locationText );
                                        PropertiesComponent.getInstance().setValue( IdeaWeatherPlugin.PROPERTY_WOEID, locationMap.get( locationText ) );
                                    }
                                    locationSelectionDialog.dispose();
                                }
                                else {
                                    if ( !locationText.equals( textField.getText() ) ) {
                                        locationText = textField.getText();
                                        new AutoComplete().execute();
                                    }
                                }
                            }
                        } );
                        locationSelectionDialog.add( textField );
                        for ( int i = 0; i < nl.getLength(); i++ ) {
                            String woeid = "";
                            String locality = "";
                            String county = "";
                            String state = "";
                            String country = "";
                            String zip = "";

                            Element element = ( Element ) nl.item( i );
                            NodeList list = element.getChildNodes();
                            for ( int j = 0; j < list.getLength(); j++ ) {
                                Element e = ( Element ) list.item( j );
                                String tagName = e.getTagName();
                                if ( "country".equals( tagName ) ) {
                                    country = e.getTextContent();
                                }
                                else if ( "woeid".equals( tagName ) ) {
                                    woeid = e.getTextContent();
                                }
                                else if ( "admin2".equals( tagName ) ) {
                                    county = e.getTextContent();
                                }
                                else if ( "admin1".equals( tagName ) ) {
                                    state = e.getTextContent();
                                }
                                else if ( "locality1".equals( tagName ) ) {
                                    locality = e.getTextContent();
                                }
                                else if ( "postal".equals( tagName ) ) {
                                    zip = e.getTextContent();
                                }
                            }
                            final JLabel label = new JLabel();
                            label.setOpaque( true );
                            label.setBorder( paddingBorder );
                            String displayText = ( locality.length() > 0 ? locality + ", " : "" )
                                                 + ( county.length() > 0 ? county + ", " : "" )
                                                 + ( state.length() > 0 ? state + ", " : "" )
                                                 + ( country.length() > 0 ? country : "" )
                                                 + ( zip.length() > 0 ? " - " + zip : "" );
                            label.setText( displayText );
                            locationMap.put( displayText, woeid );
                            label.addMouseListener( new MouseAdapter() {
                                @Override public void mousePressed( MouseEvent e ) {
                                    String loc = label.getText();
                                    if ( loc != null && loc.length() > 0 ) {
                                        location.setText( loc );
                                        PropertiesComponent.getInstance().setValue( IdeaWeatherPlugin.PROPERTY_LOCATION, loc );
                                        PropertiesComponent.getInstance().setValue( IdeaWeatherPlugin.PROPERTY_WOEID, locationMap.get( loc ) );
                                    }
                                    locationSelectionDialog.dispose();
                                }

                                @Override public void mouseEntered( MouseEvent e ) {
                                    super.mouseEntered( e );
                                    label.setBackground( Color.GREEN );
                                }

                                @Override public void mouseExited( MouseEvent e ) {
                                    super.mouseExited( e );
                                    label.setBackground( Color.WHITE );
                                }
                            } );
                            locationSelectionDialog.getContentPane().add( label );
                        }
                        locationSelectionDialog.pack();
                        Point pos = location.getLocationOnScreen();
                        locationSelectionDialog.setLocation( pos.x, pos.y );
                        locationSelectionDialog.setVisible( true );
                        textField.requestFocus();
                    }
                }
                catch ( SAXException e ) {
                    e.printStackTrace();
                }
                catch ( IOException e ) {
                    e.printStackTrace();
                }
                catch ( ParserConfigurationException e ) {
                    e.printStackTrace();
                }
            }
        }
    }
}
